/**
 * Created by qunxing.du on 2016/7/28.
 * Copyright 2016 汉威.智慧环保事业部 Limited.
 * All rights reserved.
 */
package com.hw.one.collect.zzcity.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hw.one.collect.data.DataService;
import com.hw.one.collect.dust.po.SiteInfo;
import com.hw.one.collect.dust.redis.BaseRedis;
import com.hw.one.collect.model.DataServiceType;
import com.hw.one.collect.param.SiteAirParam;
import com.hw.one.collect.po.SiteAirConcentrationPO;
import com.hw.one.collect.util.HttpClientUtil;
import com.hw.one.collect.util.OneAuthUtil;
import com.hw.one.collect.util.StringUtil;
import com.hw.one.collect.zzcity.analysis.HourAQIAnalysis;
import com.hw.one.collect.zzcity.constants.ZzCityConstants;
import com.mongodb.BasicDBList;
import org.apache.log4j.Logger;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * AQI计算数据处理器
 */
@Component
public class AnalysisDataHandler extends DataService implements IHandler{
    private static Logger log = Logger.getLogger(AnalysisDataHandler.class);

    @Resource
    private MongoTemplate mongoTemplate;
    @Resource
    private MongoTemplate mongoTemplateDev;
    @Resource
    private MongoTemplate mongoTemplateStandardSiteData;
    @Resource
    private HourAQIAnalysis hourAQIAnalysis;

    @Resource
    private BaseRedis baseRedis;
    /**
     * 处理方法
     *
     * @param o
     * @param handlerChain
     * @return
     * @throws Exception
     */
    @Override
    public synchronized Object handle(Object o,String name,  HandlerChain handlerChain) throws Exception {
        log.info("计算AQI开始");
        List<SiteAirConcentrationPO> analyzedList = hourAQIAnalysis.analysisHourData(o);
        log.info("计算AQI结束");
        log.info("插入AQI数据到生产库开始");
        String tableName = "";

        insertAnalyzedDataToProduct2(analyzedList, name);
        log.info("插入AQI数据到生产库结束:" + tableName);
//        log.info("开始调用报警规则........................");
//        dealAlarmMsg(analyzedList);
        return handlerChain.handle(o,name,handlerChain);
    }


    /**
     * 调用报警规则
     *
     * @param siteAirQualityPOList
     */
    private void dealAlarmMsg(List<SiteAirConcentrationPO> siteAirQualityPOList) {
        try {
            DecimalFormat df = new DecimalFormat("######.##");
            OneAuthUtil oneAuth = OneAuthUtil.getInstance();
            // 获取验证请求头
            Map<String, String> header = oneAuth.getAuthHeader();
            String determineRules = oneAuth.httpPre + "/api/alarmDetermine/determineRules?format=json";
            String sendAlarmInformation = oneAuth.httpPre + "/api/alarmDetermine/sendAlarmInformation?format=json";

            double pm10Sum = 0;
            double pm10Count = 0;
            for (SiteAirConcentrationPO siteAir : siteAirQualityPOList) {
                if (Double.valueOf(siteAir.getPM10()) > 0) {
                    pm10Sum += Double.valueOf(siteAir.getPM10());
                    pm10Count += 1;
                }
            }
            double pm10Avg = pm10Sum/pm10Count;
            log.info("-------PM10总含量：" + pm10Sum + "----总数：" + pm10Sum + "个站点；-----平均值：" + pm10Avg);
            Map<String, String> body = new HashMap<>();
            // 报警实例编码
            body.put("code", "nationalThreshold");
            for (SiteAirConcentrationPO siteAir : siteAirQualityPOList) {
                String[] ruleParamSet = new String[9];
                double pm10Sub = Double.valueOf(siteAir.getPM10()) / pm10Avg * 100;
                ruleParamSet[0] = "温度|" + siteAir.getTEMP();
                ruleParamSet[1] = "湿度|" + siteAir.getTEMP();
                ruleParamSet[2] = "PM10|" + siteAir.getPM10();
                ruleParamSet[3] = "PM10|" + df.format(pm10Sub) + "%";
                ruleParamSet[4] = "PM25|" + siteAir.getPM25();
                ruleParamSet[5] = "SO2|" + siteAir.getSO2();
                ruleParamSet[6] = "NO2|" + siteAir.getNO2();
                ruleParamSet[7] = "CO|" + siteAir.getCO();
                ruleParamSet[8] = "O3|" + siteAir.getO3();

                String ruleParams = StringUtil.join(ruleParamSet, ",");
                log.info("---------------ruleParams:" + ruleParams);
                body.put("ruleParams", ruleParams);
                // 请求调用报警规则匹配
                Map<String, String> response = HttpClientUtil.sendPost(determineRules, header, body);
                String resultStr = HttpClientUtil.dealResponse(response);
                if (null != resultStr) {
                    JSONObject resultObj = JSONObject.parseObject(resultStr);
                    if ("1111".equals(resultObj.getString("code"))) {
                        // 请求成功
                        JSONObject data = resultObj.getJSONObject("data");
                        if (data != null) {
                            String template = data.getString("template");   // 模板消息
                            String matchRules = data.getString("matchRules"); // 匹配的值
                            String matchCase = data.getString("matchCase"); // 匹配的模板id
                            template = template.replace("{siteName}", siteAir.getSITENAME());
                            String[] matchRuleSet = matchRules.split(",");
                            int i = 1;
                            for (String matchRule : matchRuleSet) {
                                String factor = matchRule.split("\\|")[0];
                                String factorValue = matchRule.split("\\|")[1];
                                String standardValue = matchRule.split("\\|")[2];
                                template = template.replace("{factor"+i+"}", factor).
                                        replace("{factorValue"+i+"}", factorValue).
                                        replace("{standardValue"+i+"}", standardValue);
                                i++;
                            }
                            body.put("siteCode", siteAir.getSITECODE());
                            body.put("siteName", siteAir.getSITENAME());
                            body.put("monitorTime", siteAir.getMONITORTIME());
                            body.put("matchCase", matchCase);
                            body.put("content", template);
                            // 请求调用报警规则匹配
                            Map<String, String> response2 = HttpClientUtil.sendPost(sendAlarmInformation, header, body);
                            dealResponse(response2);
                        }

                    }
                }
            }
        }catch (Exception e) {
            e.printStackTrace();
            log.error("---------------调用报警规则匹配及发送报警接口异常------");
        }

    }




    private void dealResponse(Map<String,String> response) {
        if (null != response && "200".equals(response.get("statusCode"))) {
            log.info("--------------------------------------");
            log.info(response.get("result"));
            log.info("---------------------------------------");
        }else {
            log.info("-------------------请求失败------------");
        }
    }


    /**
     * 修改计算的AQI数据
     * @param list
     */
    @Deprecated
    private void updateAnalyzedData(List<Map> list,String name){
        log.info("修改AQI数据到生产库和开发库");
        for (Map map : list){
            Object recTime =  map.get("recTime");
            Object uCode = map.get("UCode");
            Object AQI = map.get("AQI");
            Object pollutant = map.get("pollutant");
            Object AQILevel = map.get("AQILevel");
            Object PM25IAQI = map.get("PM25IAQI");
            Object PM10IAQI = map.get("PM10IAQI");
            Object COIAQI = map.get("COIAQI");
            Object SO2IAQI = map.get("SO2IAQI");
            Object NO2IAQI = map.get("NO2IAQI");
            Object O3IAQI = map.get("O3IAQI");

            Query query = Query.query(Criteria.where("recTime").is(recTime).and("UCode").is(uCode));
            Update update = Update.update("AQI",AQI).set("pollutant",pollutant).set("AQILevel",AQILevel)
                    .set("PM25IAQI",PM25IAQI).set("PM10IAQI",PM10IAQI).set("COIAQI",COIAQI)
                    .set("SO2IAQI",SO2IAQI).set("NO2IAQI",NO2IAQI).set("O3IAQI",O3IAQI);

            updateAnalyzedDataToProduct(query, update,Map.class,name);
            updateAnalyzedDataToDev(query, update,Map.class,name);
        }
    }

    private SiteAirConcentrationPO findSiteAirListByTimeAndDataSources(SiteAirParam siteAirParam, String tableName) {
        // 查询类型不等于传入的类型
        Criteria criteria = Criteria.where("SITECODE").is(siteAirParam.getSiteCode());
//        criteria.and("SITECODE").is(siteAirParam.getSiteCode());
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
//        criteria.and("MONITORTIME").gte(siteAirParam.getStartTime()).lte(siteAirParam.getEndTime());
        // 创建查询对象
        Query query = new Query(criteria).with(new Sort(Sort.Direction.DESC, "MONITORTIME").
                and(new Sort(Sort.Direction.DESC, "CREATETIME")));
        return mongoTemplateStandardSiteData.findOne(query,SiteAirConcentrationPO.class ,
                tableName + "-" + year);
    }

    /**
     * 修改计算后数据到生产库
     * @param query
     * @param update
     * @param clzz
     */
    @Deprecated
    private  void updateAnalyzedDataToProduct(Query query,Update update,Class clzz,String name){
        mongoTemplate.updateMulti(query,update,clzz,name);
    }

    /**
     * 修改计算后数据到开发库
     * @param query
     * @param update
     * @param clzz
     */
    @Deprecated
    private  void updateAnalyzedDataToDev(final Query query,final Update update,final Class clzz,final String name){
        new Thread(new Runnable() {
            @Override
            public void run() {
                mongoTemplateDev.updateMulti(query,update,clzz,name);
            }
        }).start();
    }
    /**
     * 插入计算后数据到生产库
     * @param list
     * @param name
     */
    private  void insertAnalyzedDataToProduct(BasicDBList list, String name){
        mongoTemplate.insert(list,name);
    }
    /**
     * 插入计算后数据到生产库
     * @param list
     * @param name
     */
    private  void insertAnalyzedDataToProduct2(List<SiteAirConcentrationPO> list, String name) throws ParseException {
        String tableName = "";
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        if (DataServiceType.AUDIT_FIVEMIN.name().equals(name) || DataServiceType.RAW_FIVEMIN.name().equals(name)) {
            tableName = "T_DATA_AIR_MIN_CONCENTRATION";
        }else if (DataServiceType.AUDIT_ONEHOUR.name().equals(name) || DataServiceType.RAW_ONEHOUR.name().equals(name)) {
            tableName = "T_DATA_AIR_HOUR_CONCENTRATION";
        }else if (DataServiceType.AUDIT_DAYAVG.name().equals(name) || DataServiceType.RAW_DAYAVG.name().equals(name)) {
            tableName = "T_DATA_AIR_DAY_CONCENTRATION";
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (SiteAirConcentrationPO siteAir : list) {
//            SiteAirParam siteAirParam = new SiteAirParam();
//            siteAirParam.setSiteCode(siteAir.getSITECODE());
//            siteAirParam.setDataSources(siteAir.getDATASOURCES());
//            SiteAirConcentrationPO siteAirResult = findSiteAirListByTimeAndDataSources(siteAirParam, tableName);
            log.info("siteAir:" + siteAir.toString());
//            log.debug("siteAirResult:" + siteAirResult.toString());
            // 插入之前判断
            String lastMonitorTime = baseRedis.get("zzcity" + name + siteAir.getSITECODE() + "last");
            if (lastMonitorTime == null || sdf.parse(lastMonitorTime).getTime() < sdf.parse(siteAir.getMONITORTIME()).getTime()) {
                mongoTemplateStandardSiteData.insert(siteAir,tableName + "-" + year);
                baseRedis.insert("zzcity" + name + siteAir.getSITECODE() + "last", siteAir.getMONITORTIME());
            }

//            if (siteAirResult == null) {
//                // 无数据，插入
//                log.info("--------------------无数据，插入:" + siteAir.getSITECODE()+siteAir.getMONITORTIME());
//                mongoTemplateStandardSiteData.insert(siteAir,tableName + "-" + year);
//            }else{
//                log.debug("siteAirResult:" + siteAirResult.toString());
//                Date siteAirDate = sdf.parse(siteAir.getMONITORTIME());
//                Date siteAirResultDate = sdf.parse(siteAirResult.getMONITORTIME());
//                if (siteAir.getDATASOURCES().equals(siteAirResult.getDATASOURCES()) && siteAirDate.getTime() > siteAirResultDate.getTime()) {
//                    // 判断上次是同样的数据源插入
//                    log.info("--------------------判断上次是同样的数据源插入:" + siteAir.getSITECODE()+siteAir.getMONITORTIME());
//                    mongoTemplateStandardSiteData.insert(siteAir,tableName + "-" + year);
//                }else if (siteAirDate.getTime() - siteAirResultDate.getTime() > timeLong) {
//                    // 上次更新时间跟此次插入时间大于十分钟，插入
//                    log.info("--------------------上次更新时间跟此次插入时间大于十分钟，插入:" + siteAir.getSITECODE()+siteAir.getMONITORTIME());
//                    mongoTemplateStandardSiteData.insert(siteAir,tableName + "-" + year);
//                }
//            }
        }

    }

    /**
     * 插入计算后数据到开发库
     * @param list
     * @param name
     */
    private  void insertAnalyzedDataToDev(final BasicDBList list,final String name){
        new Thread(new Runnable() {
            @Override
            public void run() {
                mongoTemplateDev.insert(list,name);
            }
        }).start();
    }


}
